﻿using System.Data.Entity;
using System.Threading.Tasks;
using KL.UFrame.Core.Exception;
using KL.UFrame.Data.Models;
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using KL.UFrame.Core.Configuration;
using KL.UFrame.Core.Result;

namespace KL.UFrame.Data.Business.Impl
{
    public class AccountBusiness:BusinessBase,IAccountBusiness
    {
        public async Task<AccountInfoModel> GetUserInfoAsync(string userName)
        {
            var user = await Db.Users.SingleOrDefaultAsync(a => a.UserName == userName);
            if(user==null) throw new ResultException(-404,"用户不存在");
            return new AccountInfoModel
            {
                UserId = user.Id,
                UserName = userName,
                RealName = user.RealName,
                Email = user.Email,
                Phone = user.PhoneNumber,
                HeadImageUrl=user.HeadImageUrl,
                Roles = GetUserRoleNames(user.Id)
            };
        }

        /// <summary>
        /// 更新用户姓名
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="newName"></param>
        /// <returns></returns>
        public async Task<int> UpdateNameAsync(string userId, string newName)
        {
            var user = await Db.Users.FirstOrDefaultAsync(a => a.Id == userId);
            if (user == null) throw new ResultException(-404, "用户不存在");
            user.RealName = newName;
            return await Db.SaveChangesAsync();
        }

        /// <summary>
        /// 更新Email
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="newEmail"></param>
        /// <returns></returns>
        public async Task<ResultMessage> UpdateEmailAsync(string userId, string newEmail)
        {
            var user = await Db.Users.FirstOrDefaultAsync(a => a.Id == userId);
            if (user == null) throw new ResultException(-404, "用户不存在");
            if (user.Email == newEmail)
            {
                return new ResultMessage(-1, "新Email不能与原来的相同");
            }
            user.Email = newEmail;
            user.EmailConfirmed = true;
            await Db.SaveChangesAsync();
            return new ResultMessage();
        }

        public async Task<int> UpdateHeadAsync(string userId, string headUrl)
        {
            var user = await Db.Users.FirstOrDefaultAsync(a => a.Id == userId);
            if (user == null) throw new ResultException(-404,"用户不存在");

            user.HeadImageUrl = headUrl;
            return await Db.SaveChangesAsync();
        }


        public async Task<bool> ValidateUserWithEmailAsync(string userName, string email)
        {
            return (await Db.Users.SingleOrDefaultAsync(a => a.UserName == userName && a.Email == email)) != null;
        }

        public bool IsInRole(string userId, string role)
        {
            return IsInRole(userId, new[] { role });
        }

        public bool IsInRole(string userId, string[] roles)
        {
            var userRoles = GetUserRoleNames(userId);
            if (userRoles == null) return false;
            if (userRoles.Contains("系统管理员")) return true;
            return userRoles.Any(roles.Contains);
        }

        public string[] GetUserRoleNames(string id, bool force = false)
        {
            var cachekey = AppConfiguration.OAuthUserRolesKey + id;
            string[] roles = force ? null : Cache.Get<string[]>(cachekey);
            if (roles == null)
            {
                var roleIds = Db.Users.Include(f => f.Roles).Single(a => a.Id == id).Roles.Select(b => b.RoleId);
                var enumerable = roleIds as IList<string> ?? roleIds.ToList();
                if (enumerable.Any())
                {
                    roles = Db.Roles.Where(a => enumerable.Contains(a.Id)).Select(b => b.Name).ToArray();

                    Cache.Add(cachekey, roles);
                    Cache.Expire(cachekey, TimeSpan.FromHours(12));
                }
            }

            return roles;
        }

        public async Task<string[]> GetUserRoleIdsAsync(string userId)
        {
            return (await Db.Users.Include(f => f.Roles).SingleAsync(a => a.Id == userId)).Roles.Select(b => b.RoleId).ToArray();
        }

        public async Task<int> ToggleUserRoleAsync(string userId, string roleId)
        {
            var result = await Db.Database.ExecuteSqlCommandAsync("exec sp_toggle_role @userId,@roleId",
                new SqlParameter("@userId", userId), new SqlParameter("@roleId", roleId));
            if (result > 0)
            {
                Cache.Remove(AppConfiguration.OAuthUserRolesKey + userId);
            }
            return result;
        }
    }
}